
const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
// 自定义的字符映射，用于替换 Base64 的字符
const customChars = 'abcdefghijklmn012opqrstuvwxyz3456+/=ABCDEFGHIJKLM789NOPQRSTUVWXYZ';
class NewBase64 {
     // private property 
     _keyStr
     mapEn
     mapDe
     _keyStr1
     mapEn1
     mapDe1
     _keyStr2
     mapEn2
     mapDe2
     constructor() {
         this._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
         this.mapEn = this._keyStr.split('');
         this.mapDe = {};
         for (let i = 0; i < this.mapEn.length; i++) {
             this.mapDe[this.mapEn[i]] = i;
         }
     }
     // public method for encoding 
     encode = (input) => {
         let output = "";
         let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
         let i = 0;
         input = this._utf8_encode(input);
         let mapEn = this.mapEn
 
         while (i < input.length) {
             chr1 = input.charCodeAt(i++);
             chr2 = input.charCodeAt(i++);
             chr3 = input.charCodeAt(i++);
             enc1 = chr1 >> 2;
             enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
             enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
             enc4 = chr3 & 63;
             if (isNaN(chr2)) {
                 enc3 = enc4 = 64;
             } else if (isNaN(chr3)) {
                 enc4 = 64;
             }
             output = output + mapEn[enc1] + mapEn[enc2] + mapEn[enc3] + mapEn[enc4];
         }
         return output;
     }
 
     // public method for decoding 
     decode = (input) => {
         let output = "";
         let chr1, chr2, chr3;
         let enc1, enc2, enc3, enc4;
         let i = 0;
         let str = input;
         let mapDe = this.mapDe
         while (i < input.length) {
             enc1 = mapDe[str.charAt(i++)];
             enc2 = mapDe[str.charAt(i++)];
             enc3 = mapDe[str.charAt(i++)];
             enc4 = mapDe[str.charAt(i++)];
             chr1 = (enc1 << 2) | (enc2 >> 4);
             chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
             chr3 = ((enc3 & 3) << 6) | enc4;
             output = output + String.fromCharCode(chr1);
             if (enc3 != 64) {
                 output = output + String.fromCharCode(chr2);
             }
             if (enc4 != 64) {
                 output = output + String.fromCharCode(chr3);
             }
         }
         output = this._utf8_decode(output);
         return output;
     }
 
     // private method for UTF-8 encoding 
     _utf8_encode = (string) => {
         string = string.replace(/\r\n/g, "\n");
         let utftext = "";
         for (let n = 0; n < string.length; n++) {
             let c = string.charCodeAt(n);
             if (c < 128) {
                 utftext += String.fromCharCode(c);
             } else if ((c > 127) && (c < 2048)) {
                 utftext += String.fromCharCode((c >> 6) | 192);
                 utftext += String.fromCharCode((c & 63) | 128);
             } else {
                 utftext += String.fromCharCode((c >> 12) | 224);
                 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                 utftext += String.fromCharCode((c & 63) | 128);
             }
         }
         return utftext;
     }
 
     // private method for UTF-8 decoding 
     _utf8_decode = (utftext) => {
         let string = "";
         let i = 0;
         let c = 0, c1 = 0, c2 = 0, c3;
         while (i < utftext.length) {
             c = utftext.charCodeAt(i);
             if (c < 128) {
                 string += String.fromCharCode(c);
                 i++;
             } else if ((c > 191) && (c < 224)) {
                 c2 = utftext.charCodeAt(i + 1);
                 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                 i += 2;
             } else {
                 c2 = utftext.charCodeAt(i + 1);
                 c3 = utftext.charCodeAt(i + 2);
                 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                 i += 3;
             }
         }
         return string;
     }
}

export let nbase64 = new NewBase64();



class NewBase642 {
    customCharsData: any = {}
    customCharsIndex: any = {}
    base64CharsData: any = {}
    base64CharsIndex: any = {}
    encryptMap: any 
    decryptMap: any 
    constructor() {
        for (let i = 0; i < base64Chars.length; i++) {
            this.base64CharsData[base64Chars[i]] = customChars[i];
            this.base64CharsIndex[base64Chars[i]] = i;
        }
        for (let i = 0; i < customChars.length; i++) {
            this.customCharsData[customChars[i]] = base64Chars[i];
            this.customCharsIndex[customChars[i]] = i;
        }
        this.generateMapping()
    }
    encode(message, secretKey) {
        // 1. Base64 编码
        const base64Encoded = nbase64.encode(message);
        // 2. 按照 secretKey 对 base64 字符串进行字符替换
        let transformed = '';
        for (let i = 0; i < base64Encoded.length; i++) {
            const char = this.base64CharsData[base64Encoded[i]];
            if (char) {
                transformed += char; // 使用自定义字符替换
            } else {
                transformed += base64Encoded[i]; // 如果不在Base64字符表中，保持不变
            }
        }

        // // 3. 变形操作 - 根据密钥再做简单的变形（例如字符反转）
        // let secretCharCodeSum = 0;
        // for (let i = 0; i < secretKey.length; i++) {
        //     secretCharCodeSum += secretKey.charCodeAt(i); // 累计密钥的 ASCII 值总和
        // }

        // // 根据密钥ASCII和的奇偶性，决定是否反转加密后的字符串
        // if (secretCharCodeSum % 2 === 0) {
        //     transformed = transformed.split('').reverse().join(''); // 反转字符串
        // }

        return transformed;
    }

    decode(encryptedMessage, secretKey) {
        let transformed = encryptedMessage;

        // // 1. 根据密钥的ASCII值总和，判断是否需要反转回来
        // let secretCharCodeSum = 0;
        // for (let i = 0; i < secretKey.length; i++) {
        //     secretCharCodeSum += secretKey.charCodeAt(i);
        // }

        // if (secretCharCodeSum % 2 === 0) {
        //     transformed = transformed.split('').reverse().join(''); // 反转回去
        // }

        // 2. 按照自定义字符映射回标准 Base64 字符
        let base64Decoded = '';
        for (let i = 0; i < transformed.length; i++) {
            const char = this.customCharsData[transformed[i]];
            if (char) {
                base64Decoded += char; // 使用 Base64 表的字符替换回去
            } else {
                base64Decoded += transformed[i]; // 不在自定义字符表中的保持不变
            }
        }
        return nbase64.decode(base64Decoded);
    }


    /**
 * 根据密钥和原始字符表进行位置偏移替换
 * @param {string} base64String - Base64 编码后的字符串
 * @param {string} secretKey - 加密使用的密钥
 * @param {boolean} isEncrypt - 是否为加密过程，true表示加密，false表示解密
 * @returns {string} - 经过位置偏移后的字符串
 */
    transformWithKey(base64String, secretKey, isEncrypt = true) {
        let result = '';
        const keyLength = secretKey.length;

        // 遍历 Base64 编码后的字符串
        for (let i = 0; i < base64String.length; i++) {
            const base64Char = base64String[i];
            const base64Index = base64Chars.indexOf(base64Char);

            if (base64Index !== -1) {
                // 获取密钥中对应位置的字符，并计算其 ASCII 值
                const keyChar = secretKey[i % keyLength];
                const keyCharCode = keyChar.charCodeAt(0);

                // 计算偏移量 (通过是否加密控制偏移方向)
                let offset = keyCharCode % customChars.length;
                if (!isEncrypt) offset = -offset;

                // 使用偏移量进行位置替换
                const newIndex = (base64Index + offset + customChars.length) % customChars.length;
                result += customChars[newIndex];
            } else {
                // 非 Base64 字符，保持不变
                result += base64Char;
            }
        }

        return result;
    }

    /**
     * Base64 变形加密算法
     * @param {string} message - 需要加密的字符串
     * @param {string} secretKey - 用于加密的密钥
     * @returns {string} - 加密后的字符串
     */
    encrypt(message, secretKey) {
        // 1. Base64 编码
        const base64Encoded = nbase64.encode(message);

        // // 2. 基于密钥进行位置偏移替换
        // const transformed = this.transformWithKey(base64Encoded, secretKey, true);

        // return transformed;

        let result = '';
        const keyLength = secretKey.length;

        // 遍历 Base64 编码后的字符串
        for (let i = 0; i < base64Encoded.length; i++) {
            const base64Char = base64Encoded[i];
            const base64Index = this.base64CharsIndex[base64Char];

            if (base64Index !== -1) {
                // 获取密钥中对应位置的字符，并计算其 ASCII 值
                const keyChar = secretKey[i % keyLength];
                const keyCharCode = keyChar.charCodeAt(0);

                // 计算偏移量 (通过是否加密控制偏移方向)
                let offset = keyCharCode % customChars.length;
                // if (!isEncrypt) offset = -offset;

                // 使用偏移量进行位置替换
                const newIndex = (base64Index + offset + customChars.length) % customChars.length;
                result += customChars[newIndex];
            } else {
                // 非 Base64 字符，保持不变
                result += base64Char;
            }
        }

        return result;
    }

    /**
     * Base64 变形解密算法
     * @param {string} encryptedMessage - 加密后的字符串
     * @param {string} secretKey - 用于解密的密钥
     * @returns {string} - 解密后的原始字符串
     */
    decrypt(encryptedMessage, secretKey) {
        // 1. 基于密钥进行位置偏移还原
        // const base64Decoded =  this.transformWithKey(encryptedMessage, secretKey, false);
        // console.log(base64Decoded)
        // // 2. Base64 解码
        // try {
        //     return atob(base64Decoded);
        // } catch (e) {
        //     throw new Error('解密失败');
        // }
        const base64Decoded = encryptedMessage

        let result = '';
        const keyLength = secretKey.length;

        // 遍历 Base64 编码后的字符串
        for (let i = 0; i < base64Decoded.length; i++) {
            const base64Char = base64Decoded[i];
            const base64Index = this.customCharsIndex[base64Char];

            if (base64Index !== -1) {
                // 获取密钥中对应位置的字符，并计算其 ASCII 值
                const keyChar = secretKey[i % keyLength];
                const keyCharCode = keyChar.charCodeAt(0);

                // 计算偏移量 (通过是否加密控制偏移方向)
                let offset = keyCharCode % customChars.length;
                offset = -offset;

                // 使用偏移量进行位置替换
                const newIndex = (base64Index + offset + customChars.length) % customChars.length;
                result += base64Chars[newIndex];
            } else {
                // 非 Base64 字符，保持不变
                result += base64Char;
            }
        }
        // 2. Base64 解码
        try {
            return nbase64.decode(result);
        } catch (e) {
            return ''
        }
    }

    generateMapping() {
        // var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        // var shuffledChars = chars.split('').sort(function() { return 0.5 - Math.random(); }).join('');
        // var encryptMap = {};
        // var decryptMap = {};
        
        // for (var i = 0; i < chars.length; i++) {
        //     encryptMap[chars[i]] = shuffledChars[i];
        //     decryptMap[shuffledChars[i]] = chars[i];
        // }
        this.encryptMap = {"0":"Q","1":"9","2":"z","3":"v","4":"h","5":"E","6":"D","7":"7","8":"F","9":"G","a":"p","b":"L","c":"f","d":"T","e":"Z","f":"H","g":"b","h":"o","i":"t","j":"q","k":"l","l":"M","m":"J","n":"I","o":"5","p":"B","q":"r","r":"d","s":"C","t":"s","u":"u","v":"0","w":"w","x":"X","y":"W","z":"O","A":"a","B":"A","C":"n","D":"R","E":"y","F":"e","G":"2","H":"m","I":"S","J":"1","K":"k","L":"c","M":"6","N":"P","O":"4","P":"U","Q":"3","R":"g","S":"8","T":"K","U":"V","V":"N","W":"Y","X":"x","Y":"i","Z":"j"};
        this.decryptMap = {"0":"v","1":"J","2":"G","3":"Q","4":"O","5":"o","6":"M","7":"7","8":"S","9":"1","p":"a","L":"b","f":"c","T":"d","Z":"e","H":"f","b":"g","o":"h","t":"i","q":"j","l":"k","M":"l","J":"m","I":"n","B":"p","r":"q","d":"r","C":"s","s":"t","u":"u","w":"w","X":"x","W":"y","O":"z","a":"A","A":"B","n":"C","R":"D","y":"E","e":"F","m":"H","S":"I","k":"K","c":"L","P":"N","U":"P","g":"R","K":"T","V":"U","N":"V","Y":"W","x":"X","i":"Y","j":"Z","Q":"0","z":"2","v":"3","h":"4","E":"5","D":"6","F":"8","G":"9"};

    }

    simpleEncode(str){
        let encryptMap = this.encryptMap
        return str.split('').map(function(char) {
            return encryptMap[char] || char; // 未定义的字符不替换
        }).join('');
    }
    simpleDecode(str){
        let decryptMap = this.decryptMap
        return str.split('').map(function(char) {
            return decryptMap[char] || char; // 未定义的字符不替换
        }).join('');
    }

}

export let nbase642 = new NewBase642();